package top.jiangqiang.qyblog.common.utils;

import cn.hutool.core.util.StrUtil;
import com.vladsch.flexmark.ast.Heading;
import com.vladsch.flexmark.ast.util.HeadingCollectingVisitor;
import com.vladsch.flexmark.ext.attributes.AttributesExtension;
import com.vladsch.flexmark.ext.autolink.AutolinkExtension;
import com.vladsch.flexmark.ext.emoji.EmojiExtension;
import com.vladsch.flexmark.ext.emoji.EmojiImageType;
import com.vladsch.flexmark.ext.emoji.EmojiShortcutType;
import com.vladsch.flexmark.ext.escaped.character.EscapedCharacterExtension;
import com.vladsch.flexmark.ext.footnotes.FootnoteExtension;
import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension;
import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension;
import com.vladsch.flexmark.ext.gitlab.GitLabExtension;
import com.vladsch.flexmark.ext.ins.InsExtension;
import com.vladsch.flexmark.ext.superscript.SuperscriptExtension;
import com.vladsch.flexmark.ext.tables.TablesExtension;
import com.vladsch.flexmark.ext.toc.TocBlock;
import com.vladsch.flexmark.ext.toc.TocExtension;
import com.vladsch.flexmark.ext.toc.internal.TocOptions;
import com.vladsch.flexmark.ext.yaml.front.matter.AbstractYamlFrontMatterVisitor;
import com.vladsch.flexmark.ext.yaml.front.matter.YamlFrontMatterExtension;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.ast.Document;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.ast.NodeVisitor;
import com.vladsch.flexmark.util.ast.VisitHandler;
import com.vladsch.flexmark.util.data.DataHolder;
import com.vladsch.flexmark.util.data.MutableDataSet;
import com.vladsch.flexmark.util.sequence.BasedSequence;
import top.jiangqiang.qyblog.common.markdown.link.CustomMediaTagsExtension;
import top.jiangqiang.qyblog.common.markdown.link.IframeLink;
import top.jiangqiang.qyblog.common.markdown.link.MatchUrl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MarkdownUtils {
    private final static DataHolder DATAHOLDER = new MutableDataSet()
            .set(Parser.EXTENSIONS, List.of(
                    TablesExtension.create(),
                    EmojiExtension.create(),
                    GitLabExtension.create(),//和美人鱼图片的语法有出入
                    StrikethroughExtension.create(),//解析和渲染删除线文本
                    YamlFrontMatterExtension.create(),
                    FootnoteExtension.create(),
                    TaskListExtension.create(),
                    TocExtension.create(),
                    AutolinkExtension.create(),
                    EscapedCharacterExtension.create(),//给标题添加id
                    InsExtension.create(),
                    CustomMediaTagsExtension.create(),
                    SuperscriptExtension.create(),
                    AttributesExtension.create()
            ))
            //下面是对插件配置的自定义
            //.set(HtmlRenderer.SOFT_BREAK, "<br />\n")//\n转换为br标签
            //.set(HtmlRenderer.ESCAPE_HTML, true)//转义HTML标签，转义之后无法在markdown中编写html
            //表情转换为unicode字符
            .set(EmojiExtension.USE_IMAGE_TYPE, EmojiImageType.UNICODE_ONLY)
            .set(TablesExtension.COLUMN_SPANS, false)
            .set(TablesExtension.APPEND_MISSING_COLUMNS, true)
            .set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
            .set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
            .set(TablesExtension.WITH_CAPTION, false)
            .set(TablesExtension.MIN_SEPARATOR_DASHES, 1)
            .set(TablesExtension.MIN_HEADER_ROWS, 1)
            .set(TablesExtension.MAX_HEADER_ROWS, 1)
            .set(EmojiExtension.USE_SHORTCUT_TYPE, EmojiShortcutType.EMOJI_CHEAT_SHEET)
            .set(FootnoteExtension.FOOTNOTE_BACK_REF_STRING, "↩︎")
            .set(TocExtension.LEVELS, TocOptions.getLevels(1, 2, 3, 4, 5, 6))
            .set(AttributesExtension.FENCED_CODE_INFO_ATTRIBUTES, true)//支持在语言后面写{}语法，将属性注入到pre标签
            .toImmutable();
    //解析markdown
    private static final Parser PARSER = Parser.builder(DATAHOLDER).build();
    private static final HtmlRenderer RENDERER = HtmlRenderer.builder(DATAHOLDER)
//            .nodeRendererFactory(new CustomNodeRenderer.Factory())
            .build();

    public static String renderMarkdown(String markdown) {
        Document document = PARSER.parse(markdown);
        NodeVisitor visitor = new NodeVisitor();
        visitor.addHandler(new VisitHandler<>(IframeLink.class, iframeLink -> {
            BasedSequence url = iframeLink.getUrl();
            iframeLink.setUrl(BasedSequence.of(MatchUrl.matchTencentVideo(url.unescape())));
        }));
        visitor.visit(document);
        return RENDERER.render(document);
    }

    /**
     * 获取目录
     *
     * @param markdown
     * @return
     */
    public static String getToc(String markdown) {
        Document document = PARSER.parse(markdown);
        HeadingCollectingVisitor visitor = new HeadingCollectingVisitor();
        visitor.collectAndGetHeadings(document);
        ArrayList<Heading> headings = visitor.getHeadings();
        StringBuilder tocStringBuilder = new StringBuilder("[TOC]\n\n");
        for (Heading heading : headings) {
            tocStringBuilder.append(heading.getChars().unescape());
            tocStringBuilder.append("\n");
        }
        String toc = tocStringBuilder.toString();
        Node tocNode = PARSER.parse(toc).getChildOfType(TocBlock.class);
        if (tocNode == null) {
            return "<ul></ul>";
        }
        String tocHtml = RENDERER.render(tocNode);
        if (StrUtil.isBlank(tocHtml)) {
            return "<ul></ul>";
        } else {
            return tocHtml;
        }
    }

    /**
     * 获取frontmatter的配置
     *
     * @param markdown
     * @return
     */
    public static Map<String, List<String>> getFrontMatter(String markdown) {
        Document document = PARSER.parse(markdown);
        // 创建Visitor对象，用于访问YamlFrontMatterBlock节点
        AbstractYamlFrontMatterVisitor visitor = new AbstractYamlFrontMatterVisitor();
        // 使用Visitor对象访问AST
        visitor.visit(document);
        return visitor.getData();
    }

    /**
     * !I[视频](https://v.qq.com/x/cover/mzc00200orkn5n8.html?j_vid=v3522q7k3fx&j_cut_vid=&j_is_win_vid=1&j_start=0)
     * !I[视频](https://v.youku.com/v_show/id_XMzk1NjM1MjAw.html?spm=a2hja.14919748_WEBHOME_NEW.drawer2.d_zj1_2&s=cc003400962411de83b1&scm=20140719.rcmd.35027.show_cc003400962411de83b1)
     * !I[视频](https://www.bilibili.com/video/BV1e94y1B7ju/?spm_id_from=333.1007.tianma.2-1-3.click)
     *
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(renderMarkdown("""     
                $a+b$$c+d$
                                
                $`1+2=3`$
                $1+2=3$ $3*4=12$
                $$
                5+6
                $$
                   
                """));

    }

}
